package com.biodiv.miracle.ioc.scanner;

import com.biodiv.miracle.support.utils.MiracleUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @Author: tianquan
 * @date: 2024-09-30  09:08
 * @Description: SPI实现工具类
 */
public class SPIResourceLoader {

    private static final String CLASSPATH = "META-INF/miracle/";

    /**
     * 获取接口的所有实现类
     */
    public static Set<String> getClassName(Class<?> interfaceClass) {
        String resourcePath = CLASSPATH + interfaceClass.getCanonicalName();
        Set<String> implementations = new LinkedHashSet<>();  // 保持顺序
        try {
            Enumeration<URL> resources = getClassLoader().getResources(resourcePath);
            while (resources.hasMoreElements()) {
                readResource(resources.nextElement(), implementations);
            }
        } catch (IOException e) {
            throw new IllegalStateException("加载实现类失败: " + resourcePath, e);
        }
        return implementations;
    }

    private static void readResource(URL resourceUrl, Set<String> implementations) {
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(resourceUrl.openStream(), StandardCharsets.UTF_8))) {

            reader.lines()
                    .map(String::trim)
                    .filter(line -> !line.isEmpty())
                    .forEach(implementations::add);

        } catch (IOException e) {
            System.err.println("警告: 无法读取资源 " + resourceUrl);
        }
    }

    private static ClassLoader getClassLoader() {
        return Thread.currentThread().getContextClassLoader();
    }

    public static List<Class<?>> loadClass(Collection<String> className) {
        if (className == null || className.isEmpty()) {
            return new ArrayList<>();
        }
        List<Class<?>> classNameList = new ArrayList<>();
        for (String s : className) {
            try {
                Class<?> aClass = MiracleUtils.getClassLoader().loadClass(s);
                classNameList.add(aClass);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        }
        return classNameList;
    }

}
